
local function set_bucket2cups(bt, cu)
    local craft = {}
    local b0 = " "
    craft[1] = {cu, cu, b0}
    craft[2] = {cu, cu, b0}
    craft[3] = {bt, b0, b0}
    return craft
end

-- hollow "checkerboard" pattern
local function set_hcp(m1, m2)
    local craft = {}
    local b0 = " "
    craft[1] = {m1, m2, m1}
    craft[2] = {m2, b0, m2}
    craft[3] = {m1, m2, m1}
    return craft
end

-- full block pattern
-- crafting patterns where one 
-- type of item fills all slots
local function set_block(m)
    local craft = {}
    if (m[1] == "(") then return end
    if m == {} then
        craft[1] = {}
        craft[2] = {}
        craft[3] = {}
    else
        craft[1] = {m, m, m}
        craft[2] = craft[1]
        craft[3] = craft[1]
    end
    return craft
end

local function set_transformer(tier)
-- transformers have the same crafting pattern
-- but the metal material used is different
    local craft = {}
    local m1 = "mesecons_materials:fiber"
    local m2 = "technic:copper_coil"
    local m3;
    digiline_send("lcd", "test ".. tier)
    if tier == "LV" then
        m3 = "default:steel_ingot"
    elseif tier == "MV" then
        m3 = "technic:carbon_steel_ingot"
    elseif tier == "HV" then
        m3 = "technic:stainless_steel_ingot"
    end
    craft[1] = {m1, m3, m1}
    craft[2] = {m2, m3, m2}
    craft[3] = {m3, m3, m3}
    return craft
end

local function set_spools(metal)
    if metal[1] == "(" then
        return
    end
    local craft = {}
    local m1;
    local m2 = "basic_materials:empty_spool"
    if metal == "silver" then
        m1 = "moreores:"..metal.._"_ingot"
    else
        m1 = "default:" .. metal .. "_ingot"
    end
    craft[1] = {m1, m2, m2}
    craft[2] = {}
    craft[3] = {}
    return craft
end

local function set_battery()
    -- can not assign "group:wood"
    local craft = {}
    craft[1] = {"default:wood", "default:copper_ingot", "default:wood"}
    craft[2] = {"default:wood", "default:tin_ingot", "default:wood"}
    craft[3] = {"default:wood", "default:copper_ingot", "default:wood"}
    return craft
end

local function grind(grain)
    local craft = {}
    craft[1] = {grain, grain, grain}
    craft[2] = {grain, "farming:mortar_pestle"}
    craft[3] = {}
    return craft
end

local function touch_response(ac, msg) 
    if msg["key_enter_field"] == nil and msg["quit"] ~= nil then
        -- ignore the event when a player closes menu
        return
    end
    if msg["key_enter_field"] == "ccoil" then
        s1 = "basic_materials:copper_wire"
        s2 = "default:steel_ingot"
        digiline_send(ac, set_hcp(s1, s2))
    elseif msg["key_enter_field"] == "battery" then
        digiline_send(ac, set_battery())
    elseif msg["clear"] ~= nil then
        digiline_send(ac, set_block({}))
        digiline_send(ac, "off")
    elseif msg["pulse"] ~= nil then
        mem.pulse = not mem.pulse
    elseif msg["key_enter_field"] == "generic" then
        goto craft
    elseif msg["transformers"] ~= nil then
        digiline_send(ac, 
        set_transformer(msg["transformers"]))
    elseif msg["spools"] ~= nil then
        digiline_send(ac, 
        set_spools(msg["spools"]))
    elseif msg["compress"] ~= nil then
        digiline_send(ac, 
        set_block(msg["compress"]))
    elseif msg["grind"] ~= nil then 
        digiline_send(ac, grind(msg["grind"]))
    elseif msg["milk"] ~= nil then
        -- if not 'cup of milk' items
        if msg["milk"] == "mobs:bucket_milk" then
            digiline_send(ac, 
                set_bucket2cups("mobs:bucket_milk", "vessels:drinking_glass"))
        else
            digiline_send(ac, 
                set_bucket2cups("bucket:bucket_empty", msg["milk"]))
        end
    end
    ::craft::
    local quantity = msg[msg["key_enter_field"]]
    if tonumber(quantity) ~= nil then
        for i=1, quantity, 1 do
            digiline_send(ac, "single")
        end
    end
end

local function spawn_button(name, label, x, y)
    local btn_width = 3
    local btn_height = 1
    local button = {}
    button.command = "addbutton"
    button["X"] = x
    button["Y"] = y
    button["W"] = btn_width
    button["H"] = btn_height
    button["name"] = name
    button["label"] = label
    return button
end

local function spawn_field(name, label, x, y, d)
    local height = 1
    local width = 3
    local field = {}
    field.command = "addfield"
    field["X"] = x
    field["Y"] = y
    field["W"] = width
    field["H"] = height
    field["name"] = name
    field["label"] = label
    field["default"] = d and d or "0"
    return field
end

local function spawn_dropdown(name, choices, x, y)
    local height = 1
    local width  = 3
    local dd = {}
    dd.command = "adddropdown"
    dd["X"] = x
    dd["Y"] = y
    dd["W"] = width
    dd["H"] = height
    dd["name"] = name
    dd["choices"] = choices
    dd["selected_id"] = 1
    return dd
end

local function touch_init(channel, pulse)
    local reset = {}
    reset.command = "clear"
    digiline_send(channel, reset)

    local offset_x = 0.5
    local offset_y = -1
    local dds = {}
    dds[1] = {name="transformers", 
              choices={"(Transformers)", "LV", "MV", "HV"}
             }
    dds[2] = {name="spools",
              choices={"(Spools)", "copper", "gold", "silver", "steel"}
             }
    dds[3] = {name="compress",
              choices={"(Compress)", "default:cobble", "default:coal_lump", "default:steel_ingot",  "default:tin_ingot", "default:copper_ingot", "default:bronze_ingot", "moreores:silver_ingot", "default:gold_ingot", "moreores:mithril_ingot",   "technic:carbon_steel_ingot", "technic:cast_iron_ingot", "technic:chromium_ingot","technic:lead_ingot",  "technic:stainless_steel_ingot", "technic:uranium0_ingot",  "technic:zinc_ingot", "basic_materials:brass_ingot",  "glooptest:akalin_ingot", "glooptest:alatro_ingot",  "glooptest:talinite_ingot",}
                }
    dds[4] = {name="grind",
              choices={"(Grind Grains)", "farming:wheat", "farming:rye", "farming:oat", "farming:barley", "farming:rice"}
             }
    dds[5] = {name="milk",
              choices = {"(milk in autocrafter is...)", "mobs:glass_milk", "farming:soy_milk", "mobs:bucket_milk"}
              }
    for i, v in ipairs(dds) do
        if i < 5 then 
            offset_y = offset_y + 1
        end
        -- fifth dropdown is placed on the second column
        -- 3 = width of dropdown
        local x = offset_x + (math.floor(i/5) * 3)
        local y = offset_y
        local dd = spawn_dropdown(v.name, v.choices, x, y)
        digiline_send(channel, dd)
    end
    offset_y = offset_y + 0.5 -- add more space b/c of labels
    local fields = {}
    fields[1] = {name="ccoil", label="Copper Coil"}
    fields[2] = {name="battery", label="RE Battery"}
    for i, v in ipairs(fields) do
        offset_y = offset_y + 1
        local f = spawn_field(v.name, v.label, 
                              offset_x, offset_y)
        digiline_send(channel, f)
    end
    offset_y = offset_y + 1
    local btns = {}
    btns[1] = {name="clear", label="Reset Craft Grid"}
    if pulse == false then
        btns[2] = {name="pulse", label="Pulse OFF"}
    else
        btns[2] = {name="pulse", label="Pulse ON"}
    end
    for i, v in ipairs(btns) do
        local b = spawn_button(v.name, v.label, 
                          offset_x, offset_y)
        digiline_send(channel, b)
        offset_x = offset_x + 3
    end
    local gen = {name="generic", label="Burst Craft"}
    digiline_send(channel, spawn_field(gen.name, gen.label,
                                       offset_x+0.5, offset_y+0.5,
                                       "96")
    )
end

local function main()
    local ts = "ts"
    local ac = "ac"
    if event.type == "program" then
        mem.pulse = false
        touch_init(ts, mem.pulse)
    elseif event.type == "digiline" and event.channel == ts then
        touch_response(ac, event.msg)
        touch_init(ts, mem.pulse)
    end
    if event.type == "interrupt" 
    or event.type == "program" then
        if mem.pulse then port.b = not port.b end
        interrupt(1)
    end
end

return main()
